/*
	extract - Extract Evo T20 XPe firmware images using this program!
	Copyright 2010, Dennis Seller

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//FILE *fp;

#define cvt32(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24))
#define cvt16(x) ((((x)&0xff)<< 8) | (((x)&0xff00)>>8))

char *replaceSlashes(char *str)
{
	int i;
	char *buf = (char *)malloc(strlen(str)+1);
	strcpy(buf, str);
	for(i=0;i<strlen(buf);i++)
		if (buf[i] == '\\')
			buf[i] = '/';
	return buf;
}

unsigned int readInt(FILE *fp)
{
	unsigned int ret;
	fread(&ret, sizeof(unsigned int), 1, fp);
	return ret;
}

unsigned int readMagic(FILE *fp)
{
	unsigned int ret;
	fread(&ret, sizeof(unsigned int), 1, fp);
	return cvt32(ret);
}

int main(int argc, char *argv[])
{
	FILE *mappings = fopen("mappings.txt", "w");
	FILE *fp = fopen(argv[1], "r");
	if (fp == NULL)
	{
		printf("Cant find the file '%s'\n", argv[1]);
		return -1;
	}

	fseek(fp, 0x21F25A, SEEK_SET);
	
	for(;;)
	{
		unsigned int magic, content_size, filename_size;
		unsigned int source_size;
		char *filename;
		char *source_name;
		char *content_buffer;
		char *fixed_name;
		FILE *writeTo;
	
		magic = readMagic(fp);
		if (magic == 0x38390000)
		{
			printf("Magic Found! (%X) @ %X\n", magic, ftell(fp));

			content_size = readInt(fp);
			readInt(fp);
			filename_size = readInt(fp);

			if (content_size == 0xFFFFFFFF)
				break;

			if (filename_size > 1000)
			{
				printf("Something went wrong, buffer overflow.\n");
				break;
			}
			filename = (char *)malloc(filename_size);
			fread(filename, 1, filename_size, fp);
			//free(filename);

			source_size = readInt(fp);
			printf("Source Filename Size: %X\n", source_size);	
			source_name = (char *)malloc(source_size);
			fread(source_name, 1, source_size, fp);

			printf("\tCreating file '%s'... ", source_name);
			fixed_name = replaceSlashes(source_name);
			writeTo = fopen(fixed_name, "w");
			if (writeTo == NULL)
			{
				printf("FAILED!\n");
				continue;
			}
			printf("OK!\n");

			printf("\tFilling buffer (%i bytes)... ", content_size);
			content_buffer = (char *)malloc(content_size);
			fread(content_buffer, 1, content_size, fp);
			printf("OK!\n");
			
			printf("\tWriting buffer (%i bytes)... ", content_size);
			fwrite(content_buffer, 1, content_size, writeTo);
			printf("OK!\n");

			printf("\tAdding mapping... ");
			fprintf(mappings, "%s %s\n", filename, source_name);
			fflush(mappings);
			printf("Done.\n");
			
			free(fixed_name);
			free(filename);
			free(source_name);
			free(content_buffer);
			fclose(writeTo);
		}
	}

	fclose(mappings);
	fclose(fp);
}
